package com.example.musicproject_b.config;

import com.example.musicproject_b.DynamicComponent.DynamicPermission;
import com.example.musicproject_b.filter.JwtFilter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

import java.util.Arrays;
import java.util.List;


@EnableWebSecurity
//开启全局方法权限控制
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    private JwtFilter jwtFilter;

    @Autowired
    private DynamicPermission dynamicPermission;


    private final List<String> permitAllEndpoints = Arrays.asList(

            "/B_admin/login",
            "/B_admin/register",
            "/B_test/test",
            "/B_admin/info",
            "http://localhost:8081/**"
    );

    @Bean
    public BCryptPasswordEncoder bCryptPasswordEncoder() {
        return new BCryptPasswordEncoder();
    }

    /**
     * 注入AuthenticationManager到spring容器中，用于用户登录时调用方法验证
     *
     * @return
     * @throws Exception
     */
    @Bean
    @Override
    public AuthenticationManager authenticationManagerBean() throws Exception {
        return super.authenticationManagerBean();
    }

    /*
     * 权限授权配置
     * */
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        super.configure(auth);
    }

    // 配置Web请求的安全性
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http

                /*
                 *在配置中使用自定义的UserDetailsService，可以实现以下功能：
                 *    根据提供的用户名从数据库或其他数据源中加载用户信息。
                 *    验证用户提供的密码，并返回匹配的用户对象。
                 *    返回用户的角色和权限信息，以便进行访问控制。
                 * 通过设置自定义的UserDetailsService，我们可以确保应用程序中的用户认证和授权逻辑是安全且符合业务需求的。
                 * */
//                .userDetailsService(dbUserDetailsManager)
                .authorizeRequests(
                        auth -> auth
                                .antMatchers(permitAllEndpoints.toArray(new String[0])).permitAll()
//                                自定义动态鉴权类
                                .anyRequest().access("@dynamicPermission.checkPermisstion(request,authentication)")
                )
//                .formLogin(form -> {
//                    form
//                            .loginPage("/B_admin/login").permitAll() //登录页面无需授权即可访问
//                            .usernameParameter("admin") //自定义表单用户名参数，默认是username
//                            .passwordParameter("password") //自定义表单密码参数，默认是password
//                            .failureUrl("/login?error") //登录失败的返回地址
//                            .successHandler(new MyAuthenticationSuccessHandler())
//                            .failureHandler(new MyAuthenticationFailureHandler())
//                    ;
//                })
                .httpBasic()
//                  此配置禁止异端进行请求，例如测试,会显示没有权限
                .and()
                .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
                .and()
                .cors()
                .and().csrf().disable()
        ;//基本授权方式


        http
                .logout(logout ->{
                    logout.logoutSuccessHandler(new MyLogoutSuccessHandler()); //注销成功时的处理
                })
                .exceptionHandling(exception  -> {
                    exception.authenticationEntryPoint(new MyAuthenticationEntryPoint());//请求未认证的接口
                    exception.accessDeniedHandler(new MyAccessDeniedHandler());
                })
                .sessionManagement(session -> {
                    session.maximumSessions(1).expiredSessionStrategy(new MySessionInformationExpiredStrategy());
                })
//                .cors(withDefaults())
        ;//跨域配置
        http.addFilterBefore(jwtFilter, UsernamePasswordAuthenticationFilter.class);
    }

}
